#include <assert.h>
#include <time.h>

#include "http.h"
#include <sys/stat.h>

// 读取一行数据直到换行符
int readLine(const SOCKET socket, char* buffer, const int bufferSize) {
    assert(buffer != NULL);
    assert(bufferSize > 0);
    int totalBytesRead = 0;
    char *ptr = buffer;
    while (totalBytesRead < bufferSize - 1) {
        const int readLen = recv(socket, ptr, 1, MSG_WAITALL);
        if (readLen == SOCKET_ERROR) return SOCKET_ERROR;
        if (readLen == 0) break;
        totalBytesRead += readLen;
        if (*ptr == '\n') {
            ptr++;
            break;
        }
        ptr += readLen;
    }
    *ptr = '\0';  // 确保字符串终止
    return totalBytesRead;
}

bool socketToFile(const SOCKET socket, FILE *file, unsigned long size) {
    assert(file != NULL);
    if (size == 0) return true;
    constexpr int maxReadSize = 65535;
    const char buffer[maxReadSize];
    fseek(file, 0, SEEK_SET);
    while (size > 0) {
        const int needReadSize = size > maxReadSize ? maxReadSize : size;
        const int readLen = recv(socket, buffer, needReadSize, 0);
        if (readLen == SOCKET_ERROR) return false;
        if (readLen == 0) return false;
        if (fwrite(buffer, sizeof(char), readLen, file) != readLen) return false;
        size -= readLen;
    }
    return true;
}

long getFileSize(FILE *file) {
    assert(file != NULL);
    const long currentPos = ftell(file);
    fseek(file, 0, SEEK_END);
    const long fileSize = ftell(file);
    fseek(file, currentPos, SEEK_SET);
    return fileSize;
}

long getFileSizeByPath(const char *filePath) {
    assert(filePath != NULL);
    struct stat fileStat;
    if (stat(filePath, &fileStat) == -1) {
        return -1;
    }
    if(S_ISREG(fileStat.st_mode) == 0) {
        return -1;
    }
    return fileStat.st_size;
}

bool isFile(const char *filePath) {
    struct stat fileStat;
    if (stat(filePath, &fileStat) != 0) {
        printf("%s get stat error: %s\n", filePath, strerror(errno));
        return false;
    }
    return S_ISREG(fileStat.st_mode) != 0;
}

bool strEndsWith(const char *str, const char *suffix) {
    if (str == NULL || suffix == NULL) return false;
    const size_t len1 = strlen(str);
    const size_t len2 = strlen(suffix);
    if (len1 < len2) return false;
    const char *pos = str + (len1 - len2);
    return strncmp(pos, suffix, len2) == 0;
}

bool strStartsWith(const char *str, const char *prefix) {
    if (str == NULL || prefix == NULL) return false;
    const size_t len1 = strlen(str);
    const size_t len2 = strlen(prefix);
    if (len1 < len2) return false;
    return strncmp(str, prefix, len2) == 0;
}

bool lastModifyOfFile(const char* filePath, char* buffer, const size_t bufferSize) {
    if (buffer == NULL) return false;
    if (!isFile(filePath)) return false;
    struct stat fileStat;
    if (stat(filePath, &fileStat) == -1) return false;
    const struct tm *gmtTime = gmtime(&fileStat.st_mtime);
    return strftime(buffer, bufferSize, "%a, %d %b %Y %H:%M:%S GMT", gmtTime) > 0;
}